﻿package {
	
	import away3d.containers.ObjectContainer3D;
	import away3d.core.math.Number3D;
	import away3d.core.utils.Cast;
	import away3d.core.base.Vertex;
	import away3d.events.MaterialEvent;
	import away3d.materials.Material;
	import away3d.materials.PhongBitmapMaterial;
	import away3d.materials.PhongMovieMaterial;
	import away3d.materials.TransformBitmapMaterial;
	import away3d.materials.WireframeMaterial;
	import away3d.primitives.LineSegment;
	import away3d.primitives.Plane;
	import away3d.materials.ColorMaterial;
	import away3d.primitives.Cube;
	import away3d.primitives.Triangle;
	import away3d.lights.DirectionalLight3D;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Rectangle;

	public class Barn extends ObjectContainer3D {
		
		//DELETE: 
		[Embed(source="../bin/images/shadow.png")]
		public var shadowBitmap:Class;
		
		protected var cube:Cube;
		protected var wainscoting:Cube;
		protected var tri:Triangle;
		protected var tri2:Triangle;
		protected var roof1:Cube;
		protected var roof2:Cube;
		private var ridgeVent:Cube;
		protected var shading:Plane;
		protected var trim:Array;
		
		protected var barnTextures:Array;
		protected var primer:ColorMaterial = new ColorMaterial(0xAAAAAA);
		protected var shinglesTexture:TransformBitmapMaterial;
		protected var shinglesBottomTexture:ColorMaterial = new ColorMaterial(0x333333);
		protected var buildingShadow:PhongBitmapMaterial;
		
		private var _yaw:Number;
		private var _roofPitch:Number = 0;
		private var overhang:Number;
		
		public function Barn() {
			createBarnTextures();
			setOverhang(12);
			addCubeBase();
			addTrim();
			addRoofTriangles();
			addRoof(45);
			addShadow();
			pushfront = true;
		}
		
	//Constructor Functions
		
		private function addRoof(initRoofPitch:Number):void {
			roof1=new Cube({width:510,height:8,depth:215,segmentsD:6,segmentsW:6});
			roof1.material = primer;
			roof1.y=89;
			roof1.z=82;
			roof1.pushback = true;
			roof2=new Cube({width:510,height:8,depth:222,segmentsD:6,segmentsW:6});
			roof2.material = primer;
			roof2.y=90;
			roof2.z = Main.START_POS;
			
			ridgeVent = new Cube( { width:510, height:8, depth:15 } );
			ridgeVent.material = primer;
			ridgeVent.y = tri.a.y - 4;
			
			setRoofPitch(initRoofPitch);
			addChild(roof1);
			addChild(roof2);
			addChild(ridgeVent);
		}
	
		private function addRoofTriangles():void {
			//tri 1
			tri=new Triangle({material:new ColorMaterial(0xffffff,{alpha:0})});
			tri.a=new Vertex(250,160,0);
			tri.b=new Vertex(250,24,150);
			tri.c=new Vertex(250,24,-150);
			tri.bothsides=true;
			tri.back = primer;

			//tri 2
			tri2=new Triangle({material:primer});
			tri2.a=new Vertex(-250,160,0);
			tri2.b=new Vertex(-250,24,150);
			tri2.c=new Vertex(-250,24,-150);
			tri2.bothsides=true;
			tri2.back = new ColorMaterial(0xffffff, { alpha:0 } );
			
			addChild(tri);
			addChild(tri2);
		}
		
		private function addCubeBase():void {
			cube=new Cube({material:primer,width:500,height:208,depth:300,pushback:true, smooth:true});//radius:20, height:200, smooth:true
			cube.cubeMaterials.bottom = new ColorMaterial(0xffffff,{alpha:0});
			cube.segmentsW = cube.segmentsH = cube.segmentsD = 3;
			cube.y = Main.START_POS;
			addChild(cube);
			
			wainscoting = new Cube();
			wainscoting.segmentsW = wainscoting.segmentsH = wainscoting.segmentsD = 3;
			wainscoting.cubeMaterials.bottom = new ColorMaterial(0xffffff,{alpha:0});
			wainscoting.cubeMaterials.top = new ColorMaterial(0xffffff,{alpha:0});
			wainscoting.y = Main.START_POS;
			addChild(wainscoting);
		}
		
		protected function addTrim():void {
			trim = new Array();
			var trimWidth:Number = Main.PIXLES_PER_FOOT / 2;
			var trimHeight:Number = (wainscoting.visible ? cube.height + wainscoting.height : cube.height);
			var trimYPosition:Number = (wainscoting.visible ? (wainscoting.y + cube.y + (cube.height-100)/2) / 2 : cube.y);
			
			trim.push(new Cube({x:cube.vertices[25].x + trimWidth/2, y:trimYPosition-1.5, z:cube.vertices[25].z-.5, width:trimWidth, height:trimHeight-3, depth:1, material:new ColorMaterial(0xFFF000)}));
			trim.push(new Cube({x:cube.vertices[25].x-.5, y:trimYPosition, z:cube.vertices[25].z + trimWidth/2, width:1, height:trimHeight, depth:trimWidth, material:new ColorMaterial(0x000FFF)}));
			trim.push(new Cube({x:cube.vertices[3].x - trimWidth/2, y:trimYPosition-1.5, z:cube.vertices[3].z-.5, width:trimWidth, height:trimHeight-3, depth:1, material:new ColorMaterial(0xFF0000)}));
			trim.push(new Cube({x:cube.vertices[3].x+.5, y:trimYPosition, z:cube.vertices[3].z + trimWidth/2, width:1, height:trimHeight, depth:trimWidth, material:new ColorMaterial(0x00FF00)}));
			trim.push(new Cube({x:cube.vertices[27].x + trimWidth/2, y:trimYPosition-1.5, z:cube.vertices[27].z+.5, width:trimWidth, height:trimHeight-3, depth:1, material:new ColorMaterial(0xFF00FF)}));
			trim.push(new Cube({x:cube.vertices[27].x-.5, y:trimYPosition, z:cube.vertices[27].z - trimWidth/2, width:1, height:trimHeight, depth:trimWidth, material:new ColorMaterial(0x00FFFF)}));
			trim.push(new Cube({x:cube.vertices[7].x - trimWidth/2, y:trimYPosition-1.5, z:cube.vertices[7].z+.5, width:trimWidth, height:trimHeight-3, depth:1, material:new ColorMaterial(0xFFFFFF)}));
			trim.push(new Cube({x:cube.vertices[7].x+.5, y:trimYPosition, z:cube.vertices[7].z - trimWidth/2, width:1, height:trimHeight, depth:trimWidth, material:new ColorMaterial(0x000000)}));
			
			for (var i:int = 0; i < trim.length; i++) addChild(trim[i]);
		}
		
		protected function removeTrim():void {
			for (var i:int = 0; i < trim.length; i++) removeChild(trim[i]);
		}
		
		private function addShadow():void {
			shading = new Plane({segmentsW:1, segmentsH:1, y:-183, width:570, height:350});
			buildingShadow = new PhongBitmapMaterial(Cast.bitmap(shadowBitmap));
			shading.material = buildingShadow;
			addChild(shading);
			shading.pushback = true;
		}
		
		public function addWainscoting():void {
			wainscoting.visible = true;
			wainscoting.width = cube.width;
			wainscoting.depth = cube.depth;
			wainscoting.height = Main.PIXLES_PER_FOOT * 4;
			wainscoting.material = new ColorMaterial(0xFF0000);
		}
		
		public function removeWainscoting():void {
			wainscoting.visible = false;
		}
		
		public function addRidgeVent():void {
			ridgeVent.height = 12;
		}
		
		public function removeRidgeVent():void {
			ridgeVent.height = 8;
		}
		
		public function createBarnTextures():void {
			barnTextures = new Array();
			barnTextures.push(new BarnTexture("Brilliant White", 0xEAEAEA));
			barnTextures.push(new BarnTexture("Ash Grey", 0xA6A490));
			barnTextures.push(new BarnTexture("Charcoal", 0x42433E));
			barnTextures.push(new BarnTexture("Bronze", 0x31291F));
			barnTextures.push(new BarnTexture("Brown", 0x392017));
			barnTextures.push(new BarnTexture("Tan", 0xA2855D));
			barnTextures.push(new BarnTexture("Light Stone", 0xCEC9A4));
			barnTextures.push(new BarnTexture("Beige", 0xE1D7B4));
			barnTextures.push(new BarnTexture("Slate Blue", 0x406276));
			barnTextures.push(new BarnTexture("Red", 0x681609));
			barnTextures.push(new BarnTexture("Evergreen", 0x0F331C));
			barnTextures.push(new BarnTexture("Pewter Gray", 0x78786C));
			barnTextures.push(new BarnTexture("Black", 0x050505));
			barnTextures.push(new BarnTexture("Clay", 0x9C8F71));
			barnTextures.push(new BarnTexture("Bone White",  0xD5D8C6));
			barnTextures.push(new BarnTexture("Burgundy", 0x281513));
			barnTextures.push(new BarnTexture("Dark Blue", 0x0A0D19));
			barnTextures.push(new BarnTexture("Avacado Green", 0x2C340D));
			barnTextures.push(new BarnTexture("Patina Green", 0x83A783));
			barnTextures.push(new BarnTexture("Scarlet Red", 0x8B0B08));
			
			//Shingles
			var shingles:Sprite = new libRoofShingles() as Sprite;
			var shingleBMD:BitmapData = new BitmapData(shingles.width, shingles.height);
			shingleBMD.draw(shingles);
			shinglesTexture = new TransformBitmapMaterial(shingleBMD, { repeat:true, precision:2, smooth:true } );
			shinglesTexture.rotation = 1.570796327;
			shinglesTexture.scaleX = .5;
		}
		
	//Functions for Barn Manipulation
		
		public function setRoofTexture(texture:Material, bottomTexture:Material):void {
			roof1.cubeMaterials.top = bottomTexture;
			roof2.cubeMaterials.top = bottomTexture;
			roof1.cubeMaterials.bottom = texture;
			roof2.cubeMaterials.bottom = texture;
			
			ridgeVent.cubeMaterials.front = texture;
			ridgeVent.cubeMaterials.back = texture;
			ridgeVent.cubeMaterials.bottom = texture;
		}
		
		public function setRoofTextureShingles():void {
			roof1.cubeMaterials.top = shinglesBottomTexture;
			roof2.cubeMaterials.top = shinglesBottomTexture;
			roof1.cubeMaterials.bottom = shinglesTexture;
			roof2.cubeMaterials.bottom = shinglesTexture;
			
			ridgeVent.cubeMaterials.front = shinglesBottomTexture;
			ridgeVent.cubeMaterials.back = shinglesBottomTexture;
			ridgeVent.cubeMaterials.bottom = shinglesBottomTexture;
		}
		
		public function setSidingTexture(texture:Material):void {
			var duplicateTexture:TransformBitmapMaterial = new TransformBitmapMaterial((texture as TransformBitmapMaterial).bitmap, { repeat:true, precision:2, smooth:true });
			duplicateTexture.scaleX = 1;
			(texture as TransformBitmapMaterial).scaleX = cube.depth/cube.width;
			
			cube.cubeMaterials.left = cube.cubeMaterials.right = duplicateTexture;
			cube.cubeMaterials.front = cube.cubeMaterials.back = texture;
			
			var triTexture:TransformBitmapMaterial = new TransformBitmapMaterial((duplicateTexture as TransformBitmapMaterial).bitmap, { repeat:true, precision:2, smooth:true } );
			triTexture.scaleX = 1.43122;
			triTexture.offsetX = 5.15;
			triTexture.rotation = 0.772308194;
			tri.back = triTexture;
			tri2.material = triTexture;
		}
		
		public function setWainscotingTexture(texture:Material):void {
			var duplicateTexture:TransformBitmapMaterial = new TransformBitmapMaterial((texture as TransformBitmapMaterial).bitmap, { repeat:true, precision:2, smooth:true });
			duplicateTexture.scaleX = 1;
			(texture as TransformBitmapMaterial).scaleX = cube.depth/cube.width;
			
			wainscoting.cubeMaterials.left = wainscoting.cubeMaterials.right = duplicateTexture;
			wainscoting.cubeMaterials.front = wainscoting.cubeMaterials.back = texture;
			
		}
		
		public function setTrimTexture(texture:Material):void {
			for (var i:int = 0; i < trim.length; i++) {
				trim[i].material = texture;
			}
			ridgeVent.cubeMaterials.left = texture;
			ridgeVent.cubeMaterials.right = texture;
			roof1.cubeMaterials.right = texture;
			roof1.cubeMaterials.left = texture;
			roof1.cubeMaterials.back = texture;
			roof2.cubeMaterials.right = texture;
			roof2.cubeMaterials.left = texture;
			roof2.cubeMaterials.front = texture;
		}
		
		public function setStructureTextures(colorIndexes:Object, shingles:Boolean):void {
			setSidingTexture(barnTextures[colorIndexes.siding].siding);
			setWainscotingTexture(barnTextures[colorIndexes.wainscoting].siding);
			setTrimTexture(barnTextures[colorIndexes.trim].trim);
			if (shingles) {
				setRoofTextureShingles(); 
			} else {
				var roofIndex:int = colorIndexes.roof;
				setRoofTexture(barnTextures[roofIndex].roof, barnTextures[roofIndex].roofBottom);
			}
		}
		
		public function resize(inWidth:Number, inDepth:Number, inHeight:Number):void {
			cube.width = inWidth;
			cube.height = inHeight - (wainscoting.visible ? wainscoting.height : 0 );
			cube.depth = inDepth;
			shading.width = inWidth*1.2;
			shading.height = inDepth * 1.2;
			shading.y = Main.START_POS - inHeight / 2;
			cube.y = Main.START_POS + (wainscoting.visible ? wainscoting.height/2 : 0);
			
			wainscoting.width = inWidth;
			wainscoting.depth = inDepth;
			wainscoting.y = cube.y - ((cube.height + wainscoting.height)/2);
			
			removeTrim();
			addTrim();
			
			//Triangles are a Bitch!
			tri.a.x = tri.b.x = tri.c.x = cube.x + inWidth / 2;
			tri2.a.x = tri2.b.x = tri2.c.x = cube.x - inWidth / 2;
			tri.b.y = tri.c.y = tri2.b.y = tri2.c.y = Main.START_POS + inHeight / 2 - 2;
			tri.b.z = tri2.b.z = inDepth / 2;
			tri.c.z = tri2.c.z = -inDepth / 2;
			
			setRoofPitch();
		}
		
		public function setRoofPitch(angle:Number = 0):void {
			if (angle != 0) {
				roof1.pitch(angle - roofPitch);
				roof2.pitch(-angle + roofPitch);
				roofPitch = angle;
			}
			
			var roofHeight:Number = (cube.depth / 2) * Math.tan(roofPitch * Math.PI / 180);
			tri.a.y = tri2.a.y = tri.b.y + roofHeight;
			
			//Roof
			var topOfRoogGapFix:int = overhang/4;
			roof1.width = roof2.width = cube.width + overhang;
			roof1.depth = Math.sqrt(Math.pow(roofHeight, 2) + Math.pow(cube.depth / 2, 2)) + overhang/2 + topOfRoogGapFix;
			roof2.depth = roof1.depth;		
			roof1.y = (tri.a.y + tri.b.y) / 2 - Math.sin(roofPitch * Math.PI / 180) * (overhang / 2);
			roof2.y = (tri.a.y + tri.b.y) / 2 - Math.sin(roofPitch * Math.PI / 180) * (overhang / 2);
			roof1.z = cube.depth / 4 + Math.cos(roofPitch * Math.PI / 180) * (overhang / 2);
			roof2.z = -cube.depth / 4 - Math.cos(roofPitch * Math.PI / 180) * (overhang / 2);
			
			//RidgeVent
			ridgeVent.width = cube.width + overhang; 
			ridgeVent.y = tri.a.y - angle/10 + (ridgeVent.height - 8)/2;
			
		}
		
		public function setOverhang(inOverhang:Number):void {
			overhang = inOverhang;
		}
		
		public function rotateOnKeyPress(keyCode:int) {
			switch (keyCode) {
				case 37 :	//left arrow key
					yaw(20);
					break;
				case 39 :	//right arrow key
					yaw(-20);
					break;
			}
			if(rotationY > 90  || rotationY < -90) showSide1();
			else showSide2();
		}
		
		public function getTextures():Array {
			return barnTextures;
		}
		
		public function blankOut():void {
			setTrimTexture(primer);
			cube.material = primer;
			wainscoting.material = primer;
			roof1.material = primer;
			roof2.material = primer;
			tri.material = primer;
			tri2.material = primer;
			ridgeVent.material = primer;
			resize(100 * Math.random(), 100 * Math.random(), 100 * Math.random());
		}
		
	//Variable Handling
		
		public function get Width():Number {
			return cube.width;
		}
		
		public function get Depth():Number {
			return cube.depth;
		}
		
		private function set roofPitch(angle:Number):void {
			_roofPitch = angle;			
		}
		
		private function get roofPitch():Number {
			return _roofPitch;
		}
		
		override public function yaw(angle:Number):void {
			_yaw = angle;
			super.yaw(angle);
		}
		
		private function showSide1():void {
			roof1.pushback = false;
			roof2.pushback = true;
		}
		
		private function showSide2():void {
			roof1.pushback = true;
			roof2.pushback = false;
		}
		
		public function ridgeVentEnabled():Boolean {
			return Boolean(ridgeVent);
		}
		
	}
}